import {
  IsString,
  IsEmail,
  IsOptional,
  IsNotEmpty,
  MinLength,
  MaxLength,
  IsEnum,
  IsBoolean,
  IsInt,
  Matches,
  ValidateNested,
  IsArray,
  Min,
  Max,
} from 'class-validator';
import { Transform } from 'class-transformer';
import { Type } from 'class-transformer';

/**
 * 更新用户信息DTO
 */
export class UpdateProfileDto {
  @IsOptional()
  @IsString({ message: '昵称必须是字符串' })
  @MinLength(2, { message: '昵称至少2个字符' })
  @MaxLength(20, { message: '昵称不能超过20个字符' })
  nickname?: string;

  @IsOptional()
  @IsEmail({}, { message: '邮箱格式不正确' })
  @MaxLength(100, { message: '邮箱不能超过100个字符' })
  email?: string;

  @IsOptional()
  @IsString({ message: '性别必须是字符串' })
  @IsEnum(['male', 'female', 'other'], {
    message: '性别只能是male、female或other',
  })
  gender?: 'male' | 'female' | 'other';

  @IsOptional()
  @IsString({ message: '生日格式不正确' })
  @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: '生日格式必须是YYYY-MM-DD' })
  birthday?: string;

  @IsOptional()
  @IsString({ message: '个人简介必须是字符串' })
  @MaxLength(500, { message: '个人简介不能超过500个字符' })
  bio?: string;

  @IsOptional()
  @IsString({ message: '地区必须是字符串' })
  @MaxLength(50, { message: '地区不能超过50个字符' })
  location?: string;

  @IsOptional()
  @IsString({ message: '职业必须是字符串' })
  @MaxLength(50, { message: '职业不能超过50个字符' })
  occupation?: string;
}

/**
 * 修改密码DTO
 */
export class ChangePasswordDto {
  @IsNotEmpty({ message: '原密码不能为空' })
  @IsString({ message: '原密码必须是字符串' })
  oldPassword: string;

  @IsNotEmpty({ message: '新密码不能为空' })
  @IsString({ message: '新密码必须是字符串' })
  @MinLength(6, { message: '新密码至少6个字符' })
  @MaxLength(20, { message: '新密码不能超过20个字符' })
  @Matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d@$!%*?&]{6,}$/, {
    message: '新密码必须包含大小写字母和数字',
  })
  newPassword: string;

  @IsNotEmpty({ message: '确认密码不能为空' })
  @IsString({ message: '确认密码必须是字符串' })
  confirmPassword: string;
}

/**
 * 阅读偏好设置DTO
 */
export class UpdateReadingPreferencesDto {
  @IsOptional()
  @IsArray({ message: '偏好的分类ID列表必须是数组' })
  @IsInt({ each: true, message: '分类ID必须是整数' })
  preferredCategories?: number[];

  @IsOptional()
  @IsEnum(['asc', 'desc'], { message: '排序方向只能是asc或desc' })
  defaultSortOrder?: 'asc' | 'desc';

  @IsOptional()
  @IsEnum(['createdAt', 'updatedAt', 'title', 'readCount', 'ratingScore'], {
    message: '默认排序字段无效',
  })
  defaultSortBy?: string;

  @IsOptional()
  @IsInt({ message: '每页显示数量必须是整数' })
  @Min(10, { message: '每页显示数量至少10个' })
  @Max(100, { message: '每页显示数量不能超过100个' })
  itemsPerPage?: number;

  @IsOptional()
  @IsBoolean({ message: '自动阅读下一章设置必须是布尔值' })
  autoReadNext?: boolean;

  @IsOptional()
  @IsBoolean({ message: '夜间模式设置必须是布尔值' })
  nightMode?: boolean;

  @IsOptional()
  @IsInt({ message: '字体大小必须是整数' })
  @Min(12, { message: '字体大小不能小于12' })
  @Max(30, { message: '字体大小不能大于30' })
  fontSize?: number;

  @IsOptional()
  @IsEnum(['default', 'serif', 'sans-serif', 'monospace'], {
    message: '字体系列无效',
  })
  fontFamily?: string;

  @IsOptional()
  @IsBoolean({ message: '显示行间距设置必须是布尔值' })
  showLineSpacing?: boolean;

  @IsOptional()
  @IsBoolean({ message: '显示章节导航设置必须是布尔值' })
  showChapterNav?: boolean;

  @IsOptional()
  @IsBoolean({ message: '启用阅读提醒设置必须是布尔值' })
  enableReadingReminder?: boolean;

  @IsOptional()
  @IsString({ message: '阅读提醒时间格式不正确' })
  @Matches(/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/, {
    message: '阅读提醒时间格式必须是HH:MM',
  })
  readingReminderTime?: string;

  @IsOptional()
  @IsBoolean({ message: '启用同步阅读进度设置必须是布尔值' })
  enableSyncProgress?: boolean;
}

/**
 * 获取活动时间线DTO
 */
export class GetActivityTimelineDto {
  @IsOptional()
  @Transform(({ value }) => parseInt(value))
  @IsInt({ message: '限制数量必须是整数' })
  @Min(1, { message: '限制数量不能小于1' })
  @Max(100, { message: '限制数量不能超过100' })
  limit?: number = 20;

  @IsOptional()
  @IsEnum(['all', 'reading', 'comment', 'favorite'], {
    message: '活动类型无效',
  })
  type?: string;

  @IsOptional()
  @IsString({ message: '开始日期格式不正确' })
  @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: '开始日期格式必须是YYYY-MM-DD' })
  startDate?: string;

  @IsOptional()
  @IsString({ message: '结束日期格式不正确' })
  @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: '结束日期格式必须是YYYY-MM-DD' })
  endDate?: string;
}

/**
 * 用户统计查询DTO
 */
export class GetUserStatsDto {
  @IsOptional()
  @IsEnum(['week', 'month', 'year', 'all'], {
    message: '统计周期无效',
  })
  period?: string = 'month';

  @IsOptional()
  @IsString({ message: '开始日期格式不正确' })
  @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: '开始日期格式必须是YYYY-MM-DD' })
  startDate?: string;

  @IsOptional()
  @IsString({ message: '结束日期格式不正确' })
  @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: '结束日期格式必须是YYYY-MM-DD' })
  endDate?: string;
}

/**
 * 导出用户数据DTO
 */
export class ExportUserDataDto {
  @IsOptional()
  @IsArray({ message: '导出类型必须是数组' })
  @IsEnum(['profile', 'favorites', 'readingHistory', 'comments', 'stats'], {
    each: true,
    message: '导出类型无效',
  })
  types?: string[];

  @IsOptional()
  @IsEnum(['json', 'csv', 'excel'], { message: '导出格式无效' })
  format?: string = 'json';

  @IsOptional()
  @IsString({ message: '开始日期格式不正确' })
  @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: '开始日期格式必须是YYYY-MM-DD' })
  startDate?: string;

  @IsOptional()
  @IsString({ message: '结束日期格式不正确' })
  @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: '结束日期格式必须是YYYY-MM-DD' })
  endDate?: string;
}

/**
 * 隐私设置DTO
 */
export class PrivacySettingsDto {
  @IsOptional()
  @IsBoolean({ message: '个人资料公开设置必须是布尔值' })
  profilePublic?: boolean;

  @IsOptional()
  @IsBoolean({ message: '阅读历史公开设置必须是布尔值' })
  readingHistoryPublic?: boolean;

  @IsOptional()
  @IsBoolean({ message: '收藏列表公开设置必须是布尔值' })
  favoritesPublic?: boolean;

  @IsOptional()
  @IsBoolean({ message: '评论记录公开设置必须是布尔值' })
  commentsPublic?: boolean;

  @IsOptional()
  @IsBoolean({ message: '统计数据公开设置必须是布尔值' })
  statsPublic?: boolean;

  @IsOptional()
  @IsBoolean({ message: '允许推荐设置必须是布尔值' })
  allowRecommendations?: boolean;

  @IsOptional()
  @IsBoolean({ message: '显示在线状态设置必须是布尔值' })
  showOnlineStatus?: boolean;
}

/**
 * 书签设置DTO
 */
export class BookmarkSettingsDto {
  @IsOptional()
  @IsBoolean({ message: '自动添加书签设置必须是布尔值' })
  autoBookmark?: boolean;

  @IsOptional()
  @IsInt({ message: '自动书签间隔必须是整数' })
  @Min(1, { message: '自动书签间隔不能小于1分钟' })
  @Max(60, { message: '自动书签间隔不能超过60分钟' })
  autoBookmarkInterval?: number;

  @IsOptional()
  @IsBoolean({ message: '同步书签设置必须是布尔值' })
  syncBookmarks?: boolean;

  @IsOptional()
  @IsInt({ message: '最大书签数量必须是整数' })
  @Min(10, { message: '最大书签数量不能小于10' })
  @Max(1000, { message: '最大书签数量不能超过1000' })
  maxBookmarks?: number;
}

/**
 * 通知设置DTO
 */
export class NotificationSettingsDto {
  @IsOptional()
  @IsBoolean({ message: '新章节更新通知设置必须是布尔值' })
  newChapterNotification?: boolean;

  @IsOptional()
  @IsBoolean({ message: '评论回复通知设置必须是布尔值' })
  commentReplyNotification?: boolean;

  @IsOptional()
  @IsBoolean({ message: '系统通知设置必须是布尔值' })
  systemNotification?: boolean;

  @IsOptional()
  @IsBoolean({ message: '推荐小说通知设置必须是布尔值' })
  recommendationNotification?: boolean;

  @IsOptional()
  @IsBoolean({ message: '邮件通知设置必须是布尔值' })
  emailNotification?: boolean;

  @IsOptional()
  @IsBoolean({ message: '推送通知设置必须是布尔值' })
  pushNotification?: boolean;
}
